package com.ncepu.thumb.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ncepu.thumb.mq.rabbit.constant.RabbitMQConstant;
import com.ncepu.thumb.constant.RedisLuaScriptConstant;
import com.ncepu.thumb.constant.ThumbConstant;
import com.ncepu.thumb.exception.BusinessException;
import com.ncepu.thumb.exception.ErrorCode;
import com.ncepu.thumb.mapper.ThumbMapper;
import com.ncepu.thumb.model.dto.DoThumbRequest;
import com.ncepu.thumb.model.entity.Thumb;
import com.ncepu.thumb.model.entity.User;
import com.ncepu.thumb.model.enums.LuaStatusEnum;
import com.ncepu.thumb.mq.msg.ThumbEvent;
import com.ncepu.thumb.service.ThumbService;
import com.ncepu.thumb.service.UserService;
import com.ncepu.thumb.utils.RedisKeyUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Arrays;

/**
 * @author 14563
 * @description 针对表【thumb】的数据库操作Service实现
 * @createDate 2025-05-10 21:18:30
 */
@Service("thumbServiceRabbitMQ")
@Slf4j
public class ThumbServiceRabbitMQImpl extends ServiceImpl<ThumbMapper, Thumb>
        implements ThumbService {

    @Resource
    private UserService userService;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private RabbitTemplate customRabbitTemplate;


    @Override
    public Boolean doThumb(DoThumbRequest doThumbRequest, HttpServletRequest request) {
        if (doThumbRequest == null || doThumbRequest.getBlogId() == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数错误");
        }
        Long blogId = doThumbRequest.getBlogId();
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR, "用户未登录");
        }

        String userThumbKey = RedisKeyUtil.getUserThumbKey(loginUser.getId());
        String blogsExistedKey = RedisKeyUtil.getBlogsExistedKey();

        // 执行Lua脚本
        Long result = redisTemplate.execute(
                RedisLuaScriptConstant.THUMB_SCRIPT_MQ, // Lua脚本
                Arrays.asList(userThumbKey, blogsExistedKey), // KEYS参数
                blogId, // ARGV[1]参数
                System.currentTimeMillis() // ARGV[2]参数
        );
        if (LuaStatusEnum.NO_BLOG.getValue() == result) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "博客不存在");
        }
        if (LuaStatusEnum.FAIL.getValue() == result) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户已点赞");
        }

        ThumbEvent thumbEvent = ThumbEvent.builder()
                .blogId(blogId)
                .userId(loginUser.getId())
                .type(ThumbEvent.EventType.INCR)
                .eventTime(LocalDateTime.now())
                .build();

        CorrelationData correlationData = new CorrelationData("INCR:" + userThumbKey + ":" + blogId);
        customRabbitTemplate.convertAndSend(RabbitMQConstant.DIRECT_EXCHANGE, RabbitMQConstant.ROUTING_KEY, thumbEvent, correlationData);

        return LuaStatusEnum.SUCCESS.getValue() == result;
    }

    @Override
    public Boolean undoThumb(DoThumbRequest doThumbRequest, HttpServletRequest request) {
        if (doThumbRequest == null || doThumbRequest.getBlogId() == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数错误");
        }
        Long blogId = doThumbRequest.getBlogId();
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR, "用户未登录");
        }

        String userThumbKey = RedisKeyUtil.getUserThumbKey(loginUser.getId());
        String blogsExistedKey = RedisKeyUtil.getBlogsExistedKey();

        // 执行Lua脚本
        Long result = redisTemplate.execute(
                RedisLuaScriptConstant.UNTHUMB_SCRIPT_MQ, // Lua脚本
                Arrays.asList(userThumbKey, blogsExistedKey), // KEYS参数
                blogId // ARGV[1]参数
        );
        if (LuaStatusEnum.NO_BLOG.getValue() == result) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "博客不存在");
        }
        if (LuaStatusEnum.FAIL.getValue() == result) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户未点赞");
        }

        ThumbEvent thumbEvent = ThumbEvent.builder()
                .blogId(blogId)
                .userId(loginUser.getId())
                .type(ThumbEvent.EventType.DECR) // 取消点赞操作
                .eventTime(LocalDateTime.now())
                .build();

        // 设置 CorrelationData，携带操作类型和 Redis 键
        CorrelationData correlationData = new CorrelationData("DECR:" + userThumbKey + ":" + blogId);
        customRabbitTemplate.convertAndSend(RabbitMQConstant.DIRECT_EXCHANGE, RabbitMQConstant.ROUTING_KEY, thumbEvent, correlationData);

        return LuaStatusEnum.SUCCESS.getValue() == result;
    }


    @Override
    public Boolean hasThumb(Long blogId, Long userId) {
        Double score = redisTemplate.opsForZSet().score(ThumbConstant.USER_THUMB_KEY_PREFIX + userId, blogId);
        return score != null;
    }
}




